/*
 * Copyright 2012 Faculty of Informatics - Masaryk University.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cz.muni.fi.pa165.creatures.web;

import cz.muni.fi.pa165.creatures.dto.CreatureDTO;
import cz.muni.fi.pa165.creatures.dto.RegionDTO;
import cz.muni.fi.pa165.creatures.services.CreatureService;
import cz.muni.fi.pa165.creatures.services.RegionService;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.security.action.Secure;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.LongTypeConverter;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;

/**
 *
 * @author hulek
 */
@UrlBinding("/regions/{$event}/{regionDTO.id}")
public class RegionsActionBean extends CreatureHuntingActionBean {

    final static Logger logger =
            Logger.getLogger(RegionsActionBean.class.getName());

    @SpringBean
    protected RegionService regionService;

    @SpringBean
    protected CreatureService creatureService;

    @ValidateNestedProperties(value = {
        @Validate(on = {"add", "save"}, field = "name",
            required = true, minlength = 3, maxlength = 255),
        @Validate(on = {"add", "save"}, field = "area",
            required = false, converter = LongTypeConverter.class, minvalue = 1, maxvalue = 100000),
        @Validate(on = {"add", "save"}, field = "description",
            required = false, minlength = 3, maxlength = 512)
    })
    private RegionDTO regionDTO;

    private List<String> selected;

    private List<CreatureDTO> creaturesOfRegion;

    public void setRegionDTO(RegionDTO regionDTO) {
        this.regionDTO = regionDTO;
    }

    public RegionDTO getRegionDTO() {
        return this.regionDTO;
    }

    public List<String> getSelected() {
        return selected;
    }

    public void setSelected(List<String> selected) {
        this.selected = selected;
    }

    public List<CreatureDTO> getCreaturesOfRegion() {
        return creaturesOfRegion;
    }

    public void setCreaturesOfRegion(List<CreatureDTO> creaturesOfRegion) {
        this.creaturesOfRegion = creaturesOfRegion;
    }

    @DefaultHandler
    public Resolution all() {
        logger.log(Level.INFO, "request to show all regions");
        return new ForwardResolution("/regions_show.jsp");
    }

    @Secure(roles ="admin")
    public Resolution create() {
        logger.log(Level.INFO, "request to create region");
        return new ForwardResolution("/regions_create.jsp");
    }

    @HandlesEvent("add")
    public Resolution add() {
        if (regionDTO == null || regionDTO.getName() == null) {
            ValidationErrors errors = new ValidationErrors();
            errors.add("name", new LocalizableError("regionDTO.name_not_set"));
            getContext().setValidationErrors(errors);
            return getContext().getSourcePageResolution();
        }
        logger.log(Level.INFO, "add({0})", regionDTO);
        regionService.create(regionDTO);
        return new RedirectResolution(this.getClass(), "all");
    }

    @Secure(roles = "admin")
    public Resolution deleteall() {
        logger.log(Level.INFO, "deleteAll()");
        regionService.deleteAll();
        return new ForwardResolution("/regions_show.jsp");
    }

    public List<RegionDTO> getAll() {
        logger.log(Level.INFO, "getAll()");
        return regionService.getAll();
    }

    public Long getCountOfCreatures() {
        logger.log(Level.INFO, "getCountOfCreaturesOf()");
        return creatureService.getCountOfCreaturesOf(regionDTO);
    }

    public Long getCount() {
        logger.log(Level.INFO, "getCount()");
        return regionService.getCount();
    }

    @Secure(roles = "admin")
    public Resolution save() {
        logger.log(Level.INFO, "save({0})", regionDTO.getId());
        regionService.update(regionDTO);
        return new ForwardResolution("/regions_show.jsp");
    }

    @Secure(roles = "admin")
    public Resolution remove() {
        logger.log(Level.INFO, "delete({0})", regionDTO.getId());
        regionService.remove(regionDTO);
        return new RedirectResolution(this.getClass());
    }

    public Resolution detail() {
        logger.log(Level.INFO, "detail({0})", regionDTO.getId());
        regionDTO = regionService.getById(Long.parseLong(regionDTO.getId()));
        creaturesOfRegion = creatureService.getCreaturesOf(regionDTO);
        logger.log(Level.INFO, "detail - region({0})", regionDTO.toString());
        logger.log(Level.INFO, "detail - creaturesOfRegion({0})", creaturesOfRegion.size());
        return new ForwardResolution("/regions_detail.jsp");
    }

    @Secure(roles = "admin")
    public Resolution edit() {
        regionDTO = regionService.getById(Long.parseLong(regionDTO.getId()));
        return new ForwardResolution("/regions_edit.jsp");
    }

    @Secure(roles = "admin")
    public Resolution deleteSelected() {
        if (selected != null) {
            for (String id : selected) {
                RegionDTO selectedRegions = regionService.getById(Long.parseLong(id));
                if (selectedRegions != null) {
                    regionService.remove(selectedRegions);
                }
            }
        }
        return new ForwardResolution("/regions_show.jsp");
    }

    @ValidationMethod(on = {"add"})
    public void validateUniqueAddRegionName() {
        ValidationErrors errors = getContext().getValidationErrors();
        if (regionService.getByName(regionDTO.getName()) != null) {
            errors.add("regionDTO.name", new LocalizableError("region.already_exists"));
        }
    }

    @ValidationMethod(on = {"save"})
    public void validateUniqueSaveRegionName() {
        ValidationErrors errors = getContext().getValidationErrors();
        RegionDTO found = regionService.getByName(regionDTO.getName());
        if (found != null && !found.getId().equals(regionDTO.getId())) {
            errors.add("regionDTO.name", new LocalizableError("region.already_exists"));
        }
    }
}
